namespace Filters.Demo
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using AForge.Imaging.Filters;
    using Filters.Demo.Core;
    using Filters.Demo.Core.FilterConfiguration;

    public class BatchImageFilter : IImageFilter
    {
        private readonly string[] searchPattern = new string[] { "*.jpg", "*.png", "*.tif", "*.bmp", "*.gif" };

        private IDictionary<string, Bitmap> images = new Dictionary<string, Bitmap>();
        private IList<FilterElement> filters = new List<FilterElement>();
        private string inputPath;

        public BatchImageFilter(string inputPath)
        {
            if (!Directory.Exists(inputPath))
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The input directory {0} does not exist.", inputPath), "inputPath");
            }

            this.inputPath = inputPath;
        }

        public event EventHandler<FilterEventArgs> FilterApplied;

        public void ApplyFilter(IFilter filter, FilterElement filterData)
        {
            foreach (var imageKey in this.images.Keys.ToList())
            {
                var filterInfo = filter as IFilterInformation;
                if (filterInfo != null)
                {
                    if (filterInfo.FormatTransalations.ContainsKey(this.images[imageKey].PixelFormat))
                    {
                        var newImage = filter.Apply(this.images[imageKey]);

                        this.images[imageKey].Dispose();
                        this.images[imageKey] = newImage;
                    }
                }
            }
            
            this.filters.Add(filterData);
            this.InvokeFilterApplied(new FilterEventArgs(this.filters));
        }

        public void Reload()
        {
            this.filters.Clear();
            this.images.Clear();

            foreach (var pattern in this.searchPattern)
            {
                foreach (var file in Directory.GetFiles(this.inputPath, pattern, SearchOption.TopDirectoryOnly))
                {
                    this.images.Add(Path.GetFileName(file), (Bitmap)Image.FromFile(file));
                }
            }
        }

        public void Save(string outputPath)
        {
            foreach (var imageKey in this.images.Keys)
            {
                this.images[imageKey].Save(Path.Combine(outputPath, imageKey));
            }
        }

        private void InvokeFilterApplied(FilterEventArgs args)
        {
            var handler = this.FilterApplied;

            if (handler != null)
            {
                handler(this, args);
            }
        }
    }
}